package net.vinote.smart.platform.service.util;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;

import net.vinote.smart.platform.comm.PlatformConst;
import net.vinote.smart.platform.comm.StringFunction;
import net.vinote.smart.platform.exception.PlatformException;
import net.vinote.smart.platform.module.log.RunLogger;
import net.vinote.smart.platform.service.SRE;
import net.vinote.smart.platform.service.bean.RoleInfo;
import net.vinote.smart.platform.service.bean.User;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Permission {
	PermissionEnum[] value() default {};

	/**
	 * 扩展权限配置
	 * 
	 * @return
	 */
	String[] ExtendedPermision() default {};

	PermissionRelation PermissionRelation() default PermissionRelation.OR;

	/**
	 * 权限枚举
	 * 
	 * @author Seer
	 *
	 */
	public enum PermissionEnum {

		/** 客户信息查询 */
		SERVICE_CUSTOMER_INFO_QUERY("SERVICE_CUSTOMER_INFO_QUERY", "客户信息查询"),
		/** 客户信息新增 */
		SERVICE_CUSTOMER_INFO_INSERT("SERVICE_CUSTOMER_INFO_INSERT", "客户信息新增"),
		/** 客户信息更新 */
		SERVICE_CUSTOMER_INFO_UPDATE("SERVICE_CUSTOMER_INFO_UPDATE", "客户信息更新"),
		/** 客户信息删除 */
		SERVICE_CUSTOMER_INFO_DELETE("SERVICE_CUSTOMER_INFO_DELETE", "客户信息删除"),
		/** 超级管理员 */
		SMART_ADMINISTRATOR("SMART_ADMINISTRATOR", "超级管理员"),
		/** 子系统新增 */
		SMART_APP_INFO_INSERT("SMART_APP_INFO_INSERT", "子系统新增"),
		/** 子系统删除 */
		SMART_APP_INFO_DELETE("SMART_APP_INFO_DELETE", "子系统删除"),
		/** 子系统查询 */
		SMART_APP_INFO_QUERY("SMART_APP_INFO_QUERY", "子系统查询"),
		/** 子系统修改 */
		SMART_APP_INFO_UPDATE("SMART_APP_INFO_UPDATE", "子系统修改"),
		/** 子系统栏目新增 */
		SMART_APP_ITEM_INSERT("SMART_APP_ITEM_INSERT", "子系统栏目新增"),
		/** 子系统栏目删除 */
		SMART_APP_ITEM_DELETE("SMART_APP_ITEM_DELETE", "子系统栏目删除"),
		/** 子系统栏目查询 */
		SMART_APP_ITEM_QUERY("SMART_APP_ITEM_QUERY", "子系统栏目查询"),
		/** 子系统栏目修改 */
		SMART_APP_ITEM_UPDATE("SMART_APP_ITEM_UPDATE", "子系统栏目修改"),
		/** 代码类别新增 */
		SMART_CODE_CATALOG_INSERT("SMART_CODE_CATALOG_INSERT", "代码类别新增"),
		/** 代码类别删除 */
		SMART_CODE_CATALOG_DELETE("SMART_CODE_CATALOG_DELETE", "代码类别删除"),
		/** 代码类别查询 */
		SMART_CODE_CATALOG_QUERY("SMART_CODE_CATALOG_QUERY", "代码类别查询"),
		/** 代码类别修改 */
		SMART_CODE_CATALOG_UPDATE("SMART_CODE_CATALOG_UPDATE", "代码类别修改"),
		/** 代码删除 */
		SMART_CODE_LIBRARY_DELETE("SMART_CODE_LIBRARY_DELETE", "代码删除"),
		/** 代码查询 */
		SMART_CODE_LIBRARY_QUERY("SMART_CODE_LIBRARY_QUERY", "代码查询"),
		/** 代码修改 */
		SMART_CODE_LIBRARY_UPDATE("SMART_CODE_LIBRARY_UPDATE", "代码修改"),
		/** 代码新增 */
		SMART_CODE_LIBRARY_INSERT("SMART_CODE_LIBRARY_INSERT", "代码新增"),
		/** 合同模板删除 */
		SMART_CONTRACT_TEMPLATE_DELETE("SMART_CONTRACT_TEMPLATE_DELETE",
				"合同模板删除"),
		/** 合同模板查询 */
		SMART_CONTRACT_TEMPLATE_QUERY("SMART_CONTRACT_TEMPLATE_QUERY", "合同模板查询"),
		/** 合同模板修改 */
		SMART_CONTRACT_TEMPLATE_UPDATE("SMART_CONTRACT_TEMPLATE_UPDATE",
				"合同模板修改"),
		/** 合同模板新增 */
		SMART_CONTRACT_TEMPLATE_INSERT("SMART_CONTRACT_TEMPLATE_INSERT",
				"合同模板新增"),
		/** 模板类目删除 */
		SMART_DW_CATALOG_DELETE("SMART_DW_CATALOG_DELETE", "模板类目删除"),
		/** 模板类目查询 */
		SMART_DW_CATALOG_QUERY("SMART_DW_CATALOG_QUERY", "模板类目查询 "),
		/** 模板类目修改 */
		SMART_DW_CATALOG_UPDATE("SMART_DW_CATALOG_UPDATE", "模板类目修改"),
		/** 模板类目新增 */
		SMART_DW_CATALOG_INSERT("SMART_DW_CATALOG_INSERT", "模板类目新增"),
		/** 模板事件删除 */
		SMART_DW_EVENT_DELETE("SMART_DW_EVENT_DELETE", "模板事件删除"),
		/** 模板事件查询 */
		SMART_DW_EVENT_QUERY("SMART_DW_EVENT_QUERY", "模板事件查询 "),
		/** 模板事件修改 */
		SMART_DW_EVENT_UPDATE("SMART_DW_EVENT_UPDATE", "模板事件修改"),
		/** 模板事件新增 */
		SMART_DW_EVENT_INSERT("SMART_DW_EVENT_INSERT", "模板事件新增"),
		/** 模板字段删除 */
		SMART_DW_LIBRARY_DELETE("SMART_DW_LIBRARY_DELETE", "模板字段删除"),
		/** 模板字段查询 */
		SMART_DW_LIBRARY_QUERY("SMART_DW_LIBRARY_QUERY", "模板字段查询 "),
		/** 模板字段修改 */
		SMART_DW_LIBRARY_UPDATE("SMART_DW_LIBRARY_UPDATE", "模板字段修改"),
		/** 模板字段新增 */
		SMART_DW_LIBRARY_INSERT("SMART_DW_LIBRARY_INSERT", "模板字段新增"),
		/** 布局类目删除 */
		SMART_LAYOUT_CATALOG_DELETE("SMART_LAYOUT_CATALOG_DELETE", "布局类目删除"),
		/** 布局类目查询 */
		SMART_LAYOUT_CATALOG_QUERY("SMART_LAYOUT_CATALOG_QUERY", "布局类目查询 "),
		/** 布局类目修改 */
		SMART_LAYOUT_CATALOG_UPDATE("SMART_LAYOUT_CATALOG_UPDATE", "布局类目修改"),
		/** 布局类目新增 */
		SMART_LAYOUT_CATALOG_INSERT("SMART_LAYOUT_CATALOG_INSERT", "布局类目新增"),
		/** 布局栏目删除 */
		SMART_LAYOUT_ITEM_DELETE("SMART_LAYOUT_ITEM_DELETE", "布局栏目删除"),
		/** 布局栏目查询 */
		SMART_LAYOUT_ITEM_QUERY("SMART_LAYOUT_ITEM_QUERY", "布局栏目查询 "),
		/** 布局栏目修改 */
		SMART_LAYOUT_ITEM_UPDATE("SMART_LAYOUT_ITEM_UPDATE", "布局栏目修改"),
		/** 布局栏目新增 */
		SMART_LAYOUT_ITEM_INSERT("SMART_LAYOUT_ITEM_INSERT", "布局栏目新增"),
		/** 表对象新增 */
		SMART_TABLE_OBJECT_INSERT("SMART_TABLE_OBJECT_INSERT", "表对象新增"),
		/** 表对象删除 */
		SMART_TABLE_OBJECT_DELETE("SMART_TABLE_OBJECT_DELETE", "表对象删除"),
		/** 表对象查询 */
		SMART_TABLE_OBJECT_QUERY("SMART_TABLE_OBJECT_QUERY", "表对象查询 "),
		/** 表对象修改 */
		SMART_TABLE_OBJECT_UPDATE("SMART_TABLE_OBJECT_UPDATE", "表对象修改"),
		/** 定时任务新增 */
		SMART_TIME_TASK_INSERT("SMART_TIME_TASK_INSERT", "定时任务新增"),
		/** 定时任务删除 */
		SMART_TIME_TASK_DELETE("SMART_TIME_TASK_DELETE", "定时任务删除"),
		/** 定时任务查询 */
		SMART_TIME_TASK_QUERY("SMART_TIME_TASK_QUERY", "定时任务查询 "),
		/** 定时任务修改 */
		SMART_TIME_TASK_UPDATE("SMART_TIME_TASK_UPDATE", "定时任务修改"),
		/** 角色信息新增 */
		SMART_ROLE_INFO_INSERT("SMART_ROLE_INFO_INSERT", "角色信息新增"),
		/** 角色信息删除 */
		SMART_ROLE_INFO_DELETE("SMART_ROLE_INFO_DELETE", "角色信息删除"),
		/** 角色信息查询 */
		SMART_ROLE_INFO_QUERY("SMART_ROLE_INFO_QUERY", "角色信息查询 "),
		/** 角色信息修改 */
		SMART_ROLE_INFO_UPDATE("SMART_ROLE_INFO_UPDATE", "角色信息修改"),
		/** 关联角色新增 */
		SMART_ROLE_RELATION_INSERT("SMART_ROLE_RELATION_INSERT", "关联角色新增"),
		/** 关联角色删除 */
		SMART_ROLE_RELATION_DELETE("SMART_ROLE_RELATION_DELETE", "关联角色删除"),
		/** 关联角色查询 */
		SMART_ROLE_RELATION_QUERY("SMART_ROLE_RELATION_QUERY", "关联角色查询 "),
		/** 关联角色修改 */
		SMART_ROLE_RELATION_UPDATE("SMART_ROLE_RELATION_UPDATE", "关联角色修改"),
		/** 系统参数新增 */
		SMART_SYSTEM_PARAM_INSERT("SMART_SYSTEM_PARAM_INSERT", "系统参数新增"),
		/** 系统参数删除 */
		SMART_SYSTEM_PARAM_DELETE("SMART_SYSTEM_PARAM_DELETE", "系统参数删除"),
		/** 系统参数查询 */
		SMART_SYSTEM_PARAM_QUERY("SMART_SYSTEM_PARAM_QUERY", "系统参数查询 "),
		/** 系统参数修改 */
		SMART_SYSTEM_PARAM_UPDATE("SMART_SYSTEM_PARAM_UPDATE", "系统参数修改"),
		/** 用户信息新增 */
		SMART_USER_INFO_INSERT("SMART_USER_INFO_INSERT", "用户信息新增"),
		/** 用户信息删除 */
		SMART_USER_INFO_DELETE("SMART_USER_INFO_DELETE", "用户信息删除"),
		/** 用户信息查询 */
		SMART_USER_INFO_QUERY("SMART_USER_INFO_QUERY", "用户信息查询 "),
		/** 用户信息修改 */
		SMART_USER_INFO_UPDATE("SMART_USER_INFO_UPDATE", "用户信息修改"),
		/** 禁用 */
		SMART_DISABLE("SMART_DISABLE", "禁用");

		PermissionEnum(String code, String name) {
			this.code = code;
			this.name = name;
		}

		private String code;
		private String name;

		public String getCode() {
			return code;
		}

		void setCode(String code) {
			this.code = code;
		}

		public String getName() {
			return name;
		}

		void setName(String name) {
			this.name = name;
		}

		public static PermissionEnum getPerimission(String code) {
			for (PermissionEnum p : values()) {
				if (p.getCode().equals(code)) {
					return p;
				}
			}
			return null;
		}
	}

	/**
	 * 权限关系
	 * 
	 * @author Seer
	 *
	 */
	public enum PermissionRelation {
		AND, OR, NOT
	}

	public class PermissionUtil {

		public static void checkPerimission(Method method,
				HttpServletRequest request) {
			if (SRE.getSystemParameter().getFirewall() == PlatformConst.No) {
				return;
			}
			Permission permission = method.getAnnotation(Permission.class);
			if (permission == null
					|| ((permission.value() == null || permission.value().length == 0) && (permission
							.ExtendedPermision() == null || permission
							.ExtendedPermision().length == 0))) {
				throw new PlatformException("未指定权限,操作存在隐患!");
			}
			if (!hasPermission(permission, request)) {
				throw new PlatformException("权限校验失败" + permission);
			}
		}

		public static boolean hasPermission(Permission need,
				HttpServletRequest request) {
			if (SRE.getSystemParameter().getFirewall() == PlatformConst.No) {
				return true;
			}
			Object obj = request.getSession().getAttribute("user");
			if (obj == null || !(obj instanceof User)) {
				throw new PlatformException("会话已超时,请重新登录");
			}
			User user = (User) obj;
			String[] roles = user.getRoleID();
			if (roles == null || roles.length == 0) {
				throw new PlatformException("当前用户未被赋予任何权限");
			}
			Set<String> permissionSet = new HashSet<String>();
			Set<PermissionEnum> perimSet = new HashSet<Permission.PermissionEnum>();
			for (String role : roles) {
				RoleInfo info = SRE.getRoleInfo(role);
				if (info == null) {
					RunLogger.getLogger().log(Level.FINEST,
							"role " + role + " is not exists now!");
					continue;
				}
				if (StringFunction.isBlank(info.getAuthGroup())) {
					RunLogger.getLogger().log(Level.FINEST,
							"role " + role + " has no auth!");
					continue;
				}
				String[] auths = info.getAuthGroup().split(",");
				for (String auth : auths) {
					PermissionEnum perm = PermissionEnum.getPerimission(auth);
					if (perm == null) {
						permissionSet.add(auth);
					} else {
						perimSet.add(perm);
					}
				}
			}
			PermissionEnum[] permArray = new PermissionEnum[perimSet.size()];
			perimSet.toArray(permArray);
			String[] perm2Array = new String[permissionSet.size()];
			permissionSet.toArray(perm2Array);
			return hasPermission(permArray, need)
					|| hasPermission(perm2Array, need);
		}

		private static boolean hasPermission(String[] permissions,
				Permission need) {

			switch (need.PermissionRelation()) {
			case OR:
				for (String cfgPerm : need.ExtendedPermision()) {
					for (String p : permissions) {
						if (p.equals(cfgPerm)) {
							return true;
						}
					}
				}
				return false;
			case AND:
				for (String cfgPerm : need.ExtendedPermision()) {
					boolean has = false;
					for (String p : permissions) {
						if (p.equals(cfgPerm)) {
							has = true;
							break;
						}
					}
					if (!has) {
						return false;
					}
				}
				return true;
			case NOT:
				for (String p : permissions) {
					for (String cfgPerm : need.ExtendedPermision()) {
						if (p.equals(cfgPerm)) {
							return false;
						}
					}
				}
				return true;
			default:
				throw new PlatformException("unsupport relation "
						+ need.PermissionRelation());
			}

		}

		private static boolean hasPermission(PermissionEnum[] permissions,
				Permission need) {
			switch (need.PermissionRelation()) {
			case OR:
				for (PermissionEnum cfgPerm : need.value()) {
					for (PermissionEnum p : permissions) {
						if (p == cfgPerm) {
							return true;
						}
					}
				}
				return false;
			case AND:
				for (PermissionEnum cfgPerm : need.value()) {
					boolean has = false;
					for (PermissionEnum p : permissions) {
						if (p == cfgPerm) {
							has = true;
							break;
						}
					}
					if (!has) {
						return false;
					}
				}
				return true;
			case NOT:
				for (PermissionEnum p : permissions) {
					for (PermissionEnum cfgPerm : need.value()) {
						if (p == cfgPerm) {
							return false;
						}
					}
				}
				return true;
			default:
				throw new PlatformException("unsupport relation "
						+ need.PermissionRelation());
			}
		}
	}

}
